import { Base64 } from "js-base64";
import crypto from "crypto-js";
import OSS from "ali-oss";
import * as OSSApi from "@/api/oss";
import { getOssToken } from "@/utils/storageUtil";

/**
 * 生成文件名及存储路径
 * @example
 * file/clue/pc/日期/文件名
 * @param { File } file
 * @param { string } ossPath
 */
export const generateFilename = (file: any, ossPath = "") => {
  if (typeof ossPath !== "string") {
    throw new TypeError("类型错误, 请传入字符串");
  }
  let ext = "";
  // #ifdef MP-WEIXIN
  if (file) {
    ext = file.split(".");
    ext = "." + ext[ext.length - 1];
  }
  // #endif
  return (
    ossPath +
    getDayNumber() +
    "/" +
    new Date().getTime() +
    "_" +
    parseInt(Math.random() * 10 ** 4) +
    ext
  );
};

/**
 * 获取但当前日期
 */
function getDayNumber() {
  const d = new Date();
  const yy = d.getFullYear();
  const mm = d.getMonth() + 1;
  const dd = d.getDate();
  return `${yy}${mm.toString().padStart(2, "0")}${dd
    .toString()
    .padStart(2, "0")}`;
}

/**
 * 获取OSS上传 formData参数
 * @param {*} ossToken
 */
export const getOssFormDataParams = () => {
  const ossToken = getOssToken();
  const date = new Date();
  date.setHours(date.getHours() + 1);
  const policyText = {
    expiration: date.toISOString(), // 设置policy过期时间。
    conditions: [
      // 限制上传大小。
      ["content-length-range", 0, 1024 * 1024 * 1024],
    ],
  };
  const policy = Base64.encode(JSON.stringify(policyText)); // policy必须为base64的string。

  const signature = computeSignature(ossToken.accessKeySecret, policy);
  const formData = {
    securityToken: ossToken.securityToken,
    OSSAccessKeyId: ossToken.accessKeyId,
    signature,
    policy,
    "x-oss-security-token": ossToken.securityToken,
  };
  return formData;
};

const computeSignature = (accessKeySecret: string, canonicalString: string) => {
  return crypto.enc.Base64.stringify(
    crypto.HmacSHA1(canonicalString, accessKeySecret)
  );
};

export enum OSSFilePath {
  answerHiveAudio = "answerHive/audio/", // 音频
  answerHivePic = "answerHive/pictures/", // 图片
  answerHiveVideo = "answerHive/video/", // 视频
}

export const ossUploadFile = (
  file: any,
  url: string,
  ossFilePath = OSSFilePath.answerHivePic
) => {
  return new Promise((resolve, reject) => {
    const fileName = generateFilename(file, ossFilePath);
    const ossFormDataParams = getOssFormDataParams();
    uni.uploadFile({
      url: url,
      filePath: file,
      name: "file",
      fileType: "image",
      formData: {
        key: fileName,
        policy: ossFormDataParams.policy,
        OSSAccessKeyId: ossFormDataParams.OSSAccessKeyId,
        success_action_status: "200",
        signature: ossFormDataParams.signature,
        "x-oss-security-token": ossFormDataParams.securityToken,
      },
      success: (res) => {
        resolve(`/${fileName}`);
      },
      complete: (res) => {
        console.log("请求完成； ", res);
      },
      fail: (res) => {
        reject(res);
      },
    });
  });
};

// 获取OOSS私有资源下载地址
export const getOssPrivateAssetUrl = (fileNmae: string) => {
  const ossToken = getOssToken();
  if (!ossToken || !ossToken.endPoint) {
    return "";
  }
  const region = ossToken.endPoint.split(".")[0];
  const client = new OSS({
    region: region,
    accessKeyId: ossToken.accessKeyId,
    accessKeySecret: ossToken.accessKeySecret,
    stsToken: ossToken.securityToken,
    bucket: ossToken.bucketName,
    expiration: ossToken.expiration,
    refreshSTSTokenInterval: 5 * 60 * 1000,
    success_action_status: "200",
    "x-oss-security-token": ossToken.securityToken,
    secure: true,
    refreshSTSToken: async () => {
      const expire = new Date(ossToken.expiration).getTime() - 1 * 60 * 1000;
      if (expire > new Date().getTime()) {
        return {
          accessKeyId: ossToken.accessKeyId,
          accessKeySecret: ossToken.accessKeySecret,
          stsToken: ossToken.securityToken,
        };
      }
      const { data } = (await OSSApi.fetchOSSConfig().catch(() => {})) as any;
      return {
        accessKeyId: data?.accessKeyId,
        accessKeySecret: data?.accessKeySecret,
        stsToken: data?.securityToken,
      };
    },
  });
  const response = {
    "content-disposition": `attachment; filename=${encodeURIComponent(
      fileNmae
    )}`,
  };
  const url = client.signatureUrl(fileNmae, {
    response,
  });
  return url;
};
